﻿using Furion.FriendlyException;

namespace Logics;

/// <summary>
/// 积分
/// </summary>
public class Points : ISingleton
{
    private readonly ISqlSugarClient db;

    /// <summary>
    /// 
    /// </summary>
    /// <param name="db"></param>
    public Points(ISqlSugarClient db)
    {
        this.db = db;
    }

    /// <summary>
    /// 设置积分并记录日志
    /// </summary>
    /// <returns></returns>
    public async Task<bool> SetAndLog(int usedType, int userId, dynamic point, string memo)
    {
        var pointInfo = await db.Queryable<Entity.ClientPoints>()

            .FirstAsync(x => x.ClientId == userId);

        if (pointInfo == null)
        {
            pointInfo = new Entity.ClientPoints
            {
                ClientId = userId,

                Points = 0
            };

            pointInfo.Id = await db.Insertable(pointInfo).ExecuteReturnIdentityAsync();
        }

        if (usedType == 0)
        {
            if (pointInfo.Points < point) throw Oops.Oh("积分不足");

            pointInfo.Points -= point;
        }
        else
        {
            pointInfo.Points += point;
        }

        try
        {
            db.Ado.BeginTran();

            var log = new Entity.ClientPointsLog
            {
                After = pointInfo.Points,

                Points = point,

                ClientId = userId,

                UsedType = usedType,

                Memo = memo
            };

            await db.Insertable(log).ExecuteCommandAsync();

            await db.Updateable(pointInfo).ExecuteCommandAsync();

            db.Ado.CommitTran();

            return true;
        }
        catch (Exception)
        {
            db.Ado.RollbackTran();

            return false;
        }
    }

    /// <summary>
    /// 添加积分
    /// </summary>
    /// <param name="userId"></param>
    /// <param name="point"></param>
    /// <param name="memo"></param>
    /// <returns></returns>
    public async Task<bool> Add(int userId, dynamic point, string memo)
    {
        return await SetAndLog(1, userId, point, memo);
    }

    /// <summary>
    /// 扣除
    /// </summary>
    /// <param name="userId"></param>
    /// <param name="point"></param>
    /// <param name="memo"></param>
    /// <returns></returns>
    public async Task<bool> Deduct(int userId, dynamic point, string memo)
    {
        return await SetAndLog(0, userId, point, memo);
    }
}
